package com.xinke.module.system.service.user;

import cn.hutool.core.collection.CollUtil;
import com.xinke.component.common.enums.CommonStatusEnum;
import com.xinke.component.common.util.sno.IdGen;
import com.xinke.module.system.convert.dept.DeptConvert;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import com.xinke.module.system.model.vo.user.*;
import com.xinke.module.system.model.entity.user.DeptDO;
import com.xinke.component.common.pojo.PageResult;
import com.xinke.component.common.pojo.PageParam;
import com.xinke.component.common.util.object.BeanUtils;

import com.xinke.module.system.mapper.user.DeptMapper;

import static com.xinke.component.common.exception.util.ServiceExceptionUtil.exception;
import static com.xinke.component.common.util.collection.CollectionUtils.convertSet;
import static com.xinke.module.system.enums.ErrorCodeConstants.*;

/**
 * 部门 Service 实现类
 *
 * @author yzx
 */
@Service
@Validated
public class DeptServiceImpl implements DeptService {

    @Resource
    private DeptMapper deptMapper;

    @Override
    public Long createDept(DeptSaveReqVO createReqVO) {
        // 插入
        DeptDO dept = BeanUtils.toBean(createReqVO, DeptDO.class);
        if(Objects.isNull(dept.getDeptId())){
            dept.setDeptId(IdGen.nextId());
        }
        deptMapper.insert(dept);
        // 返回
        return dept.getDeptId();
    }

    @Override
    public void updateDept(DeptSaveReqVO updateReqVO) {
        // 校验存在
        validateDeptExists(updateReqVO.getDeptId());
        // 更新
        DeptDO updateObj = BeanUtils.toBean(updateReqVO, DeptDO.class);
        deptMapper.updateById(updateObj);
    }

    @Override
    public void deleteDept(Long deptId) {
        // 校验存在
        validateDeptExists(deptId);
        // 删除
        deptMapper.deleteById(deptId);
    }

    private void validateDeptExists(Long deptId) {
        if (deptMapper.selectById(deptId) == null) {
            throw exception(null);
        }
    }

    @Override
    public DeptDO getDept(Long deptId) {
        return deptMapper.selectById(deptId);
    }

    @Override
    public PageResult<DeptDO> getDeptPage(DeptPageReqVO pageReqVO) {
        return deptMapper.selectPage(pageReqVO);
    }

    @Override
    public void validateDeptList(Collection<Long> deptIds) {
        if (CollUtil.isEmpty(deptIds)) {
            return;
        }
        // 获得科室信息
        Map<Long, DeptDO> deptMap = getDeptMap(deptIds);
        // 校验
        deptIds.forEach(id -> {
            DeptDO dept = deptMap.get(id);
            if (dept == null) {
                throw exception(DEPT_NOT_FOUND);
            }
            if (!CommonStatusEnum.ENABLE.getStatus().equals(dept.getDeptStatus())) {
                throw exception(DEPT_NOT_ENABLE, dept.getDeptName());
            }
        });
    }

    @Override
    public List<DeptDO> getDeptList(Collection<Long> deptIds) {
        if (CollUtil.isEmpty(deptIds)) {
            return Collections.emptyList();
        }
        return deptMapper.selectBatchIds(deptIds);
    }

    @Override
    public List<DeptRespVO> getAllDepts() {
        List<DeptDO> deptDos = deptMapper.selectList();
        if (CollUtil.isEmpty(deptDos)) {
            return Collections.emptyList();
        }
        deptDos = sortDeptsByShowSort(deptDos);
        return buildDeptTree(deptDos);
    }

    private List<DeptRespVO> buildDeptTree(List<DeptDO> deptDos) {
        // 构建部门树形结构（已按show_sort排序）
        List<DeptRespVO> parentDept = deptDos.stream()
                .filter(deptDO -> deptDO.getParentId() == DeptDO.ID_ROOT)
                .map(deptDO -> DeptConvert.INSTANCE.convert(deptDO))
                .collect(Collectors.toList());
        // 为每个顶级部门设置子部门
        parentDept.forEach(dept -> {
            dept.setId(dept.getId());
            dept.setLabel(dept.getDeptName());
            dept.setChildren(getDeptChildren(dept.getDeptId(), deptDos));

        });
        return parentDept;
    }

    // 递归获取子部门
    private List<DeptRespVO> getDeptChildren(Long parentId, List<DeptDO> deptDos) {
        List<DeptRespVO> children = deptDos.stream()
                .filter(dept -> parentId.equals(dept.getParentId()))
                .map(deptDO -> DeptConvert.INSTANCE.convert(deptDO))
                .collect(Collectors.toList());
        // 递归设置子部门的子部门
        children.forEach(dept -> {
            dept.setId(dept.getId());
            dept.setLabel(dept.getDeptName());
            dept.setChildren(getDeptChildren(dept.getDeptId(), deptDos));
        });
        return children.isEmpty() ? null : children;
    }

    private List<DeptDO> sortDeptsByShowSort(List<DeptDO> deptDOs) {
        return deptDOs.stream()
                .sorted(Comparator.comparingInt(DeptDO::getShowSort))
                .collect(Collectors.toList());
    }

    @Override
    public List<DeptDO> getChildDeptList(Collection<Long> ids) {
        List<DeptDO> children = new LinkedList<>();
        // 遍历每一层
        Collection<Long> parentIds = ids;
        for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下，存在死循环
            // 查询当前层，所有的子部门
            List<DeptDO> depts = deptMapper.selectListByParentId(parentIds);
            // 1. 如果没有子部门，则结束遍历
            if (CollUtil.isEmpty(depts)) {
                break;
            }
            // 2. 如果有子部门，继续遍历
            children.addAll(depts);
            parentIds = convertSet(depts, DeptDO::getDeptId);
        }
        return children;
    }
}